<template>
    <div class="apk-analysis-box">
        <div class="btn-box">
            <!-- 正在上传中 -->
            <div v-if="uploading">
                <el-button size="small" type="success" v-if="isCancleUpload" @click="resumeUpload">继续上传</el-button>
                <el-button size="small" type="primary" v-else @click="stopUpload">暂停上传</el-button>
                <el-button size="small" type="info" @click="cancleUpload">取消上传</el-button>
            </div>
            <el-upload
                v-else
                class="upload-btn"
                action="string"
                accept=".apk"
                :show-file-list="false"
                :http-request="uploadChange">
                <el-button size="small" type="primary">选择并上传</el-button>
            </el-upload>
            <div v-if="apkUrl" class="get-msg-box">
                <el-button size="small" v-if="showgetApkMsgBtnkey" type="info" @click="getApkMsg(client.key)">分析apk</el-button>
                <el-button size="small" type="info" v-else-if="!percent" @click="getApkMsgUrl">分析apk链接</el-button>
                <el-button size="small" type="info" v-else-if="percent && uploadhandler" @click="cancleGetPercent">取消分析</el-button>
            </div>
        </div>
        <el-progress v-if="percent" :percentage="percent" style="width:500px;"></el-progress>
        <span v-if="uploading && fileSize">{{(fileSize * percent / 100) | sizeFilter}} / {{fileSize | sizeFilter}}</span>
        <!-- <Progress  :percent="percent" status="active" /> -->
    </div>
</template>

<script>
import OSS from 'ali-oss'
export default {
    data () {
        return {
            percent: 0, // 上传进度
            apkUrl: '', // apkURL
            client: {},
            fileSize: 0, // 文件大小
            uploadhandler: false, // 手动分析apk链接（三方）取消开关
            showgetApkMsgBtnkey: false, // 上传完毕可根据key分析
            uploading: false, // 正在上传中
            isCancleUpload: false // 是否取消了上传（可恢复为继续上传）
        }
    },

    props: ['url'],

    watch: {
        url (val) {
            this.apkUrl = val
        }
    },

    created () {
        this.apkUrl = this.url
        // 判断是否有断点续传
        let tempCheckpoint = window.localStorage.getItem('checkpoint')
        let OSSclient = window.localStorage.getItem('OSSclient')
        let apkFile = window.localStorage.getItem('apkFile')
        let apkPercent = window.localStorage.getItem('apkPercent')
        if (tempCheckpoint && OSSclient && apkFile) {
            apkFile = JSON.parse(apkFile)
            if (apkFile.id === this.$route.query.id) {
                // 提示继续断点续传
                let size = apkFile.size / 1024
                if (size <= 1024) {
                    size = size.toFixed(2)
                    size = size + ' KB'
                } else {
                    size = size / 1024
                    if (size <= 1024) {
                        size = size.toFixed(2)
                        size = size + ' MB'
                    } else {
                        size = size / 1024
                        size = size.toFixed(2)
                        size = size + ' GB'
                    }
                }
                this.$confirm(`检测到上次有apk文件上传未完成，选择原文件后会自动继续上传（如选择其他文件则销毁上次上传记录），文件名称： ${apkFile.name}，文件大小： ${size}${apkPercent ? ('，已传进度：' + apkPercent + '%') : ''}`, '温馨提示', {
                    confirmButtonText: '上传其他文件',
                    cancelButtonText: '我知道了',
                    type: 'warning'
                }).then(() => {
                    window.localStorage.setItem('checkpoint', '')
                    window.localStorage.setItem('OSSclient', '')
                    window.localStorage.setItem('apkFile', '')
                    this.$message({
                        type: 'success',
                        message: '已为您清除上次上传记录'
                    })
                }).catch(() => {
                })
            }
        }
    },

    mounted () {
    },

    methods: {
        // 获取信息
        async getApkMsg (key) {
            this.percent = 0
            let time = setInterval(() => {
                this.percent += 10
                if (this.percent >= 90) {
                    clearInterval(time)
                }
            }, 300)
            let params = {}
            params.key = key
            let res = await this.$http.get('/game/getApkMsgByOssFile', {
                params: params
            })
            clearInterval(time)
            if (res.code === '0') {
                this.percent = 100
                this.$message({
                    type: 'success',
                    message: '分析成功，已为您自动替换分析的信息。'
                })
                this.$emit('getMsg', res.data)
                setTimeout(() => {
                    this.percent = 0
                }, 500)
            } else {
                this.percent = 0
                this.$message({
                    type: 'error',
                    message: res.desc
                })
            }
        },

        // 分析url
        async getApkMsgUrl () {
            if (this.percent) return
            // 如果是我们自己的地址，直接获取key分析
            let apkArr = this.apkUrl.split('/static/apk/')
            if (apkArr.length > 1) {
                let key = 'static/apk/' + apkArr[1]
                this.getApkMsg(key)
                return
            }
            this.percent = 0
            let params = {}
            params.url = this.apkUrl
            let res = await this.$http.get('/game/getApkMsgByOssFile', {
                params: params
            })
            if (res.code === '0' || res.code === '-1') {
                this.uploadhandler = true
                this.percent = 1
                this.timerId = setInterval(() => {
                    this.getPercent()
                }, 2000)
            } else {
                this.percent = 0
                this.$message({
                    type: 'error',
                    message: res.desc
                })
            }
        },

        // 分析url 进度
        async getPercent () {
            let res = await this.$http.get('/game/getUploadProgress', {
                params: {
                    url: this.apkUrl
                }
            })
            if (res.code === '0') {
                this.percent = res.data.percent || 1
                if (res.data.succeed) {
                    this.getApkMsg(res.data.key)
                    clearInterval(this.timerId)
                    this.uploadhandler = false
                }
            } else {
                this.percent = 0
                clearInterval(this.timerId)
                this.$message({
                    type: 'error',
                    message: res.desc
                })
            }
        },

        // 取消分析
        cancleGetPercent () {
            this.uploadhandler = false
            this.percent = 0
            clearInterval(this.timerId)
        },

        // 获取文件
        async uploadChange (file) {
            this.file = file.file // 选取上传文件
            if (!this.file) return
            // 重置初始化状态
            this.uploadhandler = false
            this.showgetApkMsgBtnkey = false
            this.uploading = false
            this.isCancleUpload = false
            // 获取文件大小
            this.fileSize = this.file.size

            // 判断是否有断点续传
            let tempCheckpoint = window.localStorage.getItem('checkpoint')
            let OSSclient = window.localStorage.getItem('OSSclient')
            let apkFile = window.localStorage.getItem('apkFile') ? JSON.parse(window.localStorage.getItem('apkFile')) : ''
            if (tempCheckpoint && OSSclient && apkFile && parseInt(apkFile.id || 0) === parseInt(this.$route.query.id || 0)) {
                if (apkFile.name !== this.file.name || apkFile.size !== this.file.size) {
                    this.$confirm(`检测到上次有apk文件上传未完成，此次上传并非原文件。继续上传会覆盖原记录，请问是否继续上传？`, '温馨提示', {
                        confirmButtonText: '继续上传',
                        cancelButtonText: '取消上传',
                        type: 'warning'
                    }).then(() => {
                        let apkFile = {
                            name: this.file.name,
                            size: this.file.size,
                            id: this.$route.query.id
                        }
                        window.localStorage.setItem('apkFile', JSON.stringify(apkFile))
                        this.getOssUploadSign()
                    }).catch(() => {
                        this.$message({
                            type: 'success',
                            message: '取消上传成功，请重新选择文件上传'
                        })
                    })
                } else {
                    // 继续上传
                    this.resumeUpload()
                }
            } else {
                // 正常上传
                // 保存上传文件的信息
                let apkFile = {
                    name: this.file.name,
                    size: this.file.size,
                    id: this.$route.query.id
                }
                window.localStorage.setItem('apkFile', JSON.stringify(apkFile))
                this.getOssUploadSign()
            }
        },

        // 获取上传参数
        async getOssUploadSign () {
            let res = await this.$http.get('/file/getOssUploadSign')
            if (res.code === '0') {
                this.client = res.data || {}
                window.localStorage.setItem('OSSclient', JSON.stringify(res.data))
                this.aliClient = new OSS({
                    region: this.client.region,
                    accessKeyId: this.client.accessKeyId,
                    accessKeySecret: this.client.accessKeySecret,
                    bucket: this.client.bucket
                })

                this.multipartUpload(this.file)
            } else {
                this.$message({
                    type: 'error',
                    message: res.desc
                })
            }
        },

        // 直接上传
        async putObject (file) {
            let time = setInterval(() => {
                this.percent += 5
                if (this.percent >= 90) {
                    clearInterval(time)
                }
            }, 500)
            // object-key可以自定义为文件名（例如file.txt）或目录（例如abc/test/file.txt）的形式，实现将文件上传至当前Bucket或Bucket下的指定目录。
            let result = await this.aliClient.put(this.client.key, file)
            this.getApkMsg(result.name)
            this.percent = 100
            setTimeout(() => {
                this.percent = 0
            }, 300)
            clearInterval(time)
        },

        // 分片上传
        async multipartUpload (file) {
            this.uploading = true
            try {
                // object-key可以自定义为文件名（例如file.txt）或目录（例如abc/test/file.txt）的形式，实现将文件上传至当前Bucket或Bucket下的指定目录。
                await this.aliClient.multipartUpload(this.client.key, file, {
                    progress: this.progress
                })
            } catch (e) {
                console.log(e)
            }
        },

        // 上传进度
        progress (p, checkpoint) {
            window.localStorage.setItem('checkpoint', JSON.stringify(checkpoint))
            p = parseInt(p * 100)
            this.percent = p || 1
            window.localStorage.setItem('apkPercent', this.percent)
            if (this.percent >= 100) {
                // 上传完毕
                this.uploading = false
                // 清空存储记录
                window.localStorage.setItem('checkpoint', '')
                window.localStorage.setItem('OSSclient', '')
                window.localStorage.setItem('apkFile', '')
                // 上报下载地址
                this.$emit('uploadEnd', this.client.downloadUrl)
                // 展示分析按钮
                this.showgetApkMsgBtnkey = true
                setTimeout(() => {
                    this.percent = 0
                }, 300)
                this.$message({
                    type: 'success',
                    message: '上传成功'
                })
            }
        },

        // 暂停上传
        stopUpload () {
            this.aliClient.cancel()
            this.isCancleUpload = true
        },

        // 取消上传
        cancleUpload () {
            this.aliClient.cancel()
            this.uploading = false
            window.localStorage.setItem('checkpoint', '')
            window.localStorage.setItem('OSSclient', '')
            window.localStorage.setItem('apkFile', '')
            this.percent = 0
        },

        // 继续上传
        async resumeUpload () {
            this.percent = window.localStorage.getItem('apkPercent') - 0
            this.uploading = true
            this.isCancleUpload = false
            let tempCheckpoint = window.localStorage.getItem('checkpoint')
            let OSSclient = window.localStorage.getItem('OSSclient')
            if (tempCheckpoint && OSSclient) {
                tempCheckpoint = JSON.parse(tempCheckpoint)
                OSSclient = JSON.parse(OSSclient)
                this.client = OSSclient
                tempCheckpoint.file = this.file
            } else {
                this.uploading = false
                // 无法继续上传
                this.$message({
                    type: 'error',
                    message: '数据丢失，无法继续上传'
                })
                return
            }
            this.aliClient = new OSS({
                region: OSSclient.region,
                accessKeyId: OSSclient.accessKeyId,
                accessKeySecret: OSSclient.accessKeySecret,
                bucket: OSSclient.bucket
            })
            try {
                await this.aliClient.multipartUpload(tempCheckpoint.name, this.file.name, {
                    progress: this.progress,
                    checkpoint: tempCheckpoint
                })
            } catch (e) {
                console.log(e)
            }
        }
    },
    filters: {
        sizeFilter (data) {
            if (!data) {
                return '0KB'
            }
            let size = data / 1024
            if (size <= 1024) {
                size = size.toFixed(2)
                return size + ' KB'
            } else {
                size = size / 1024
                if (size <= 1024) {
                    size = size.toFixed(2)
                    return size + ' MB'
                } else {
                    size = size / 1024
                    size = size.toFixed(2)
                    return size + ' GB'
                }
            }
        }
    },

    destroyed () {
        clearInterval(this.timerId)
    }
}
</script>

<style lang="scss" scoped>
    .apk-analysis-box {
        .btn-box {
            display: flex;
            .get-msg-box {
                margin-left: 10px;
            }
        }
    }
</style>
